﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;

namespace MapEditorSDG
{
    [Serializable()]

    class GameCell: ISerializable
    {
        //Type of existing field through the game.
        public const string STRING_TYPE_VOID = "ingame_void";
        public const string STRING_TYPE_PLAIN = "plain";
        public const string STRING_TYPE_THUNDRA = "thundra";
        public const string STRING_TYPE_DESERT = "desert";
        public const string STRING_TYPE_HILL = "hill";
        public const string STRING_TYPE_MOUNTAIN = "mountain";
        public const string STRING_TYPE_VOLCANO = "volcano";
        public const string STRING_TYPE_RIVER = "river";
        public const string STRING_TYPE_WATER = "water";
        public const string STRING_TYPE_SWAMP = "swamp";
        public const string STRING_TYPE_BUSH = "bush";
        public const string STRING_TYPE_ICE = "ice";
        public const string STRING_TYPE_LAVA = "lava";
        public const string STRING_TYPE_SNOW = "snow";
        public const string STRING_TYPE_ROAD = "road";
        public const string STRING_TYPE_NOMANLAND = "nomanland";
        public const string STRING_TYPE_VULCAN = "vulcan";
        public const string STRING_TYPE_PRECARIOUS_MOUNTAIN = "precarious_mountain";
        public const string STRING_TYPE_DEEP_WATER = "deep_water";

        public const int NUMBER_OF_FIELD = 18;

        //String used for serialization.
        public const string SERIA_ROW = "Row";
        public const string SERIA_COLUMN = "Column";
        public const string SERIA_FIELD = "Field";
        public const string SERIA_SPAWN = "spawn";
        public const string SERIA_LEVEL = "level";

        //Cell size.
        public const int CELL_WIDTH = 40;
        public const int CELL_HEIGHT = 40;

        private Label cell;
        private int row;
        private int column;

        private bool isSpawn;
        private string fieldType;
        private bool isSelected;

        //Indicate the height of the cliff, if there's any.
        private int level;

        public GameCell()
        {
            row = -1;
            column = -1;

            isSelected = false;
            fieldType = STRING_TYPE_PLAIN;
            isSpawn = false;
            level = 0;

            cell = new Label();
            cell.BorderStyle = BorderStyle.FixedSingle;

            //Creation of a empty cell.
            this.cell.Click += new System.EventHandler(OnSelection);

            this.cell.SetBounds(0, 0, CELL_WIDTH, CELL_HEIGHT);
        }

        public GameCell(SerializationInfo _info, StreamingContext _ctxt)
        {
            row = (int) _info.GetValue(SERIA_ROW, typeof(int));
            column = (int) _info.GetValue(SERIA_COLUMN, typeof(int));

            isSelected = false;
            fieldType = (string) _info.GetValue(SERIA_FIELD, typeof(string));
            isSpawn = (bool) _info.GetValue(SERIA_SPAWN, typeof(bool));
            level = (int)_info.GetValue(SERIA_LEVEL, typeof(int));

            cell = new Label();
            cell.BorderStyle = BorderStyle.FixedSingle;

            //Creation of a empty cell.
            this.cell.Parent = null;
            this.cell.SetBounds(column * CELL_WIDTH, (int)row * GameCell.CELL_HEIGHT + ((column % 2) * GameCell.CELL_HEIGHT / 2), CELL_WIDTH, CELL_HEIGHT);

            this.cell.Click += new System.EventHandler(OnSelection);

            cell.Text = level.ToString();
            ChooseColor();
        }

        public void GetObjectData(SerializationInfo _info, StreamingContext _ctxt)
        {
            _info.AddValue(SERIA_ROW, row);
            _info.AddValue(SERIA_COLUMN, column);
            _info.AddValue(SERIA_FIELD, fieldType);
            _info.AddValue(SERIA_SPAWN, isSpawn);
            _info.AddValue(SERIA_LEVEL, level);
        }

        public GameCell(Control _parent, int _row = 0, int _column = 0)
        {
            row = _row;
            column = _column;

            isSelected = false;
            fieldType = STRING_TYPE_PLAIN;
            level = 0;
            isSpawn = false;

            cell = new Label();
            cell.BorderStyle = BorderStyle.FixedSingle;

            //Creation of a empty cell.
            this.cell.Parent = _parent;
            this.cell.SetBounds(column * CELL_WIDTH, (int) row * GameCell.CELL_HEIGHT + ((column % 2) * GameCell.CELL_HEIGHT / 2), CELL_WIDTH, CELL_HEIGHT);

            this.cell.Click += new System.EventHandler(OnSelection);

            cell.Text = level.ToString();
            ChooseColor();
        }

        public void Reset(int _column, int _row)
        {
            column = _column;
            row = _row;
            fieldType = STRING_TYPE_PLAIN;
            isSelected = false;
            level = 0;
            isSpawn = false;

            cell.Text = level.ToString();
            ChooseColor();
        }

        public void Locate(int _row, int _column)
        {
            row = _row;
            column = _column;

            ChooseColor();
        }

        public void ChooseColor()
        {
            if (isSpawn)
                this.Cell.BackColor = System.Drawing.Color.CornflowerBlue;
            else
                //Paint the cell with the good color. Pair cells has a different color from the impair ones.
                switch (fieldType)
                {
                    case STRING_TYPE_WATER:
                        this.cell.BackColor = System.Drawing.Color.FromArgb(100, System.Drawing.Color.DeepSkyBlue);
                        break;
                    case STRING_TYPE_DEEP_WATER:
                        this.cell.BackColor = System.Drawing.Color.FromArgb(100, System.Drawing.Color.Blue);
                        break;
                    case STRING_TYPE_MOUNTAIN:
                        this.cell.BackColor = System.Drawing.Color.FromArgb(100, System.Drawing.Color.Chocolate);
                        break;
                    case STRING_TYPE_HILL:
                        this.cell.BackColor = System.Drawing.Color.FromArgb(100, System.Drawing.Color.BurlyWood);
                        break;
                    case STRING_TYPE_VOID:
                        this.cell.BackColor = System.Drawing.Color.FromArgb(215, System.Drawing.Color.Black);
                        break;
                    default:
                            this.cell.BackColor = System.Drawing.Color.FromArgb(50, System.Drawing.Color.AliceBlue);
                        break;
                }

            cell.Text = level.ToString();
        }

        private void OnSelection(Object sender, EventArgs e)
        {
            isSelected = !isSelected;

            if (isSelected)
                this.cell.BackColor =  System.Drawing.Color.FromArgb(150, System.Drawing.Color.LightGreen);
            else
                ChooseColor();
        }

        public void ApplyChange(string _item, bool _isSpawn = false, int _level = 0)
        {
            fieldType = _item;
            isSpawn = _isSpawn;
            level = _level;

            ChooseColor();
        }

        //Accessors.
        public int Row
        {
            get
            {
                return row;
            }
            set
            {
                row = value;
            }
        }

        public int Column
        {
            get
            {
                return column;
            }
            set
            {
                column = value;
            }
        }

        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                isSelected = value;
            }
        }

        public string FieldType
        {
            get { return fieldType; }
            set { fieldType = value; }
        }

        public Label Cell
        {
            get { return cell; }
            set { cell = value; }
        }

    }
}
